import { Path, Shape, ShapeGeometry, Vector3 } from "three";

export default class EntityUtils {
    /**
     * 铝模板 TODO:抽下挖孔的逻辑（开发阶段先不管）
     * @param l 长
     * @param w 宽
     * @param minl 最小长 
     * @param maxl 最大长
     * @param minw 最小宽
     * @param maxw 最大宽
     * @param fh 上边框高度
     * @param bh 下边框高度
     * @param lh 左边框高度
     * @param rh 右边框高度
     * @param hw 横肋宽度
     * @param hh 横肋高度
     * @param vw 竖肋宽度
     * @param vh 竖肋宽度
     * @param r  孔直径
     * @param dis 孔到接触面距离
     * @param tbp 上下边框孔位置
     * @param lrp 左右边框孔位置
     * @param hp 横肋位置
     * @param vp 竖肋位置
     * @param scr 螺杆孔直径
     * @param scrp 螺杆孔位置
     * @param lrt 左右厚度
     * @param tbt 上下厚度
     * @param bt 背板厚度
     */
    static getBoardVI(l: number, w: number, minl: number, maxl: number, minw: number, maxw: number, fh: number, bh: number, lh: number, rh: number,
        hw: number, hh: number, vw: number, vh: number, r: number, dis: number, tbp: any[], lrp: any[], hp: any[], vp: any[], scr: number, scrp: any[],
        lrt: number = 0.07, tbt: number = 0.08, bt: number = 0.04, corner: boolean = false, ch: number = 0.45, cort:number = 0.08): any[] {

        let vertices: any[] = [];
        let indices: any[] = [];
        let facevec: any[] = [];

        // 数据
        let count: number = 0;

        // 竖条
        for (let i = 0; i < vp.length; i++) {
            let pos = vp[i];
            let tvec = [
                new Vector3(pos + vw / 2, tbt, vh + bt),
                new Vector3(pos - vw / 2, tbt, vh + bt),
                new Vector3(pos - vw / 2, tbt, 0 + bt),
                new Vector3(pos + vw / 2, tbt, 0 + bt),

                new Vector3(pos + vw / 2, tbt, vh + bt)
            ];
            let bvec = [
                new Vector3(pos + vw / 2, l - tbt, vh + bt),
                new Vector3(pos - vw / 2, l - tbt, vh + bt),
                new Vector3(pos - vw / 2, l - tbt, bt),
                new Vector3(pos + vw / 2, l - tbt, bt),

                new Vector3(pos + vw / 2, l - tbt, vh + bt)
            ];

            let vvec = EntityUtils.getVIF(bvec, tvec, count);
            count = vvec[3];

            vertices.push(...vvec[0]);
            indices.push(...vvec[1]);
            facevec.push(...vvec[2]);
        }

        // 横条
        for (let i = 0; i < hp.length; i++) {
            let pos = hp[i];
            let tvec = [
                new Vector3(lrt, pos - hh / 2, hw + bt),
                new Vector3(lrt, pos - hh / 2, bt),
                new Vector3(w - lrt, pos - hh / 2, bt),
                new Vector3(w - lrt, pos - hh / 2, hw + bt),

                new Vector3(lrt, pos - hh / 2, hw + bt)
            ];
            let bvec = [
                new Vector3(lrt, pos + hh / 2, hw + bt),
                new Vector3(lrt, pos + hh / 2, bt),
                new Vector3(w - lrt, pos + hh / 2, bt),
                new Vector3(w - lrt, pos + hh / 2, hw + bt),

                new Vector3(lrt, pos + hh / 2, hw + bt)
            ];

            let vvec = EntityUtils.getVIF(bvec, tvec, count);
            count = vvec[3];

            vertices.push(...vvec[0]);
            indices.push(...vvec[1]);
            facevec.push(...vvec[2]);
        }

        //左挖孔
        let lfBottomVec = [
            new Vector3(0, 0, 0),
            new Vector3(0, 0, lh),
            new Vector3(0, l, lh),
            new Vector3(0, l, 0),
            new Vector3(0, 0, 0)
        ]

        let lfTopVec = [
            new Vector3(lrt, 0, 0),
            new Vector3(lrt, 0, lh),
            new Vector3(lrt, l, lh),
            new Vector3(lrt, l, 0),
            new Vector3(lrt, 0, 0)
        ]

        let lfside = EntityUtils.getSideVIF(lfTopVec, lfBottomVec, count);

        vertices.push(...lfside[0]);
        indices.push(...lfside[1]);
        facevec.push(...lfside[2]);
        count = lfside[3];

        let lrpos = EntityUtils.getPosByDis(lrp, dis);

        let leftData = EntityUtils.getHolesShapeGeometry(lh, l, 0, r, lrpos, count, 'x', false)

        vertices.push(...leftData[0]);
        indices.push(...leftData[1]);
        facevec.push([
            new Vector3(0, 0, 0),
            new Vector3(0, 0, lh),
            new Vector3(0, l, lh),
            new Vector3(0, l, 0)
        ]);

        count = leftData[2] + 1;

        let rightData = EntityUtils.getHolesShapeGeometry(lh, l, lrt, r, lrpos, count, 'x', true)

        vertices.push(...rightData[0]);
        indices.push(...rightData[1]);
        facevec.push([
            new Vector3(lrt, 0, 0),
            new Vector3(lrt, 0, lh),
            new Vector3(lrt, l, lh),
            new Vector3(lrt, l, 0)
        ]);

        count = rightData[2] + 1;
        // 右挖孔
        let rtBottomVec = [
            new Vector3(w - lrt, 0, 0),
            new Vector3(w - lrt, 0, rh),
            new Vector3(w - lrt, l, rh),
            new Vector3(w - lrt, l, 0),
            new Vector3(w - lrt, 0, 0)
        ]

        let rtTopVec = [
            new Vector3(w, 0, 0),
            new Vector3(w, 0, lh),
            new Vector3(w, l, lh),
            new Vector3(w, l, 0),
            new Vector3(w, 0, 0)
        ]

        let rtside = EntityUtils.getSideVIF(rtTopVec, rtBottomVec, count);

        vertices.push(...rtside[0]);
        indices.push(...rtside[1]);
        facevec.push(...rtside[2]);
        count = rtside[3];

        leftData = EntityUtils.getHolesShapeGeometry(rh, l, w - lrt, r, lrpos, count, 'x', false)

        vertices.push(...leftData[0]);
        indices.push(...leftData[1]);
        facevec.push([
            new Vector3(w - lrt, 0, 0),
            new Vector3(w - lrt, 0, rh),
            new Vector3(w - lrt, l, rh),
            new Vector3(w - lrt, l, 0)
        ]);

        count = leftData[2] + 1;

        rightData = EntityUtils.getHolesShapeGeometry(rh, l, w, r, lrpos, count, 'x', true)

        vertices.push(...rightData[0]);
        indices.push(...rightData[1]);
        facevec.push([
            new Vector3(w, 0, 0),
            new Vector3(w, 0, lh),
            new Vector3(w, l, lh),
            new Vector3(w, l, 0)
        ]);

        count = rightData[2] + 1;
        // 上挖孔
        let tpBottomVec = [
            new Vector3(0, l - tbt, 0),
            new Vector3(0, l - tbt, fh),
            new Vector3(w, l - tbt, fh),
            new Vector3(w, l - tbt, 0),
            new Vector3(0, l - tbt, 0)
        ]

        let tpTopVec = [
            new Vector3(0, l, 0),
            new Vector3(0, l, fh),
            new Vector3(w, l, fh),
            new Vector3(w, l, 0),
            new Vector3(0, l, 0)
        ]

        let tpside = EntityUtils.getSideVIF(tpBottomVec, tpTopVec, count);

        vertices.push(...tpside[0]);
        indices.push(...tpside[1]);
        facevec.push(...tpside[2]);
        count = tpside[3];

        let tbpos = EntityUtils.getPosByDis(tbp, dis);
        leftData = EntityUtils.getHolesShapeGeometry(fh, w, l - tbt, r, tbpos, count, 'y', true)

        vertices.push(...leftData[0]);
        indices.push(...leftData[1]);
        facevec.push([
            new Vector3(0, l - tbt, 0),
            new Vector3(0, l - tbt, fh),
            new Vector3(w, l - tbt, fh),
            new Vector3(w, l - tbt, 0)
        ]);

        count = leftData[2] + 1;

        rightData = EntityUtils.getHolesShapeGeometry(fh, w, l, r, tbpos, count, 'y', false)

        vertices.push(...rightData[0]);
        indices.push(...rightData[1]);
        facevec.push([
            new Vector3(0, l, 0),
            new Vector3(0, l, fh),
            new Vector3(w, l, fh),
            new Vector3(w, l, 0)
        ]);

        count = rightData[2] + 1;

        // 下挖孔
        tpBottomVec = [
            new Vector3(0, 0, 0),
            new Vector3(0, 0, fh),
            new Vector3(w, 0, fh),
            new Vector3(w, 0, 0),
            new Vector3(0, 0, 0)
        ]

        tpTopVec = [
            new Vector3(0, tbt, 0),
            new Vector3(0, tbt, fh),
            new Vector3(w, tbt, fh),
            new Vector3(w, tbt, 0),
            new Vector3(0, tbt, 0)
        ]

        tpside = EntityUtils.getSideVIF(tpBottomVec, tpTopVec, count);

        vertices.push(...tpside[0]);
        indices.push(...tpside[1]);
        facevec.push(...tpside[2]);
        count = tpside[3];

        leftData = EntityUtils.getHolesShapeGeometry(fh, w, 0, r, tbpos, count, 'y', true)

        vertices.push(...leftData[0]);
        indices.push(...leftData[1]);
        facevec.push([
            new Vector3(0, 0, 0),
            new Vector3(0, 0, fh),
            new Vector3(w, 0, fh),
            new Vector3(w, 0, 0)
        ]);

        count = leftData[2] + 1;

        rightData = EntityUtils.getHolesShapeGeometry(fh, w, tbt, r, tbpos, count, 'y', false)

        vertices.push(...rightData[0]);
        indices.push(...rightData[1]);
        facevec.push([
            new Vector3(0, tbt, 0),
            new Vector3(0, tbt, fh),
            new Vector3(w, tbt, fh),
            new Vector3(w, tbt, 0)

        ]);

        count = rightData[2] + 1;

        // 背板
        let backBottomVec = [
            new Vector3(0, 0, bt),
            new Vector3(w, 0, bt),
            new Vector3(w, l, bt),
            new Vector3(0, l, bt),
            new Vector3(0, 0, bt)
        ]

        let backTopVec = [
            new Vector3(0, 0, 0),
            new Vector3(w, 0, 0),
            new Vector3(w, l, 0),
            new Vector3(0, l, 0),
            new Vector3(0, 0, 0)
        ]


        let backside = EntityUtils.getSideVIF(backTopVec, backBottomVec, count);

        vertices.push(...backside[0]);
        indices.push(...backside[1]);
        facevec.push(...backside[2]);
        count = backside[3];

        leftData = EntityUtils.getHolesShapeGeometry(w, l, bt, r, scrp, count, 'z', false)

        vertices.push(...leftData[0]);
        indices.push(...leftData[1]);
        facevec.push([
            new Vector3(0, 0, bt),
            new Vector3(w, 0, bt),
            new Vector3(w, l, bt),
            new Vector3(0, l, bt)
        ]);

        count = leftData[2] + 1;

        rightData = EntityUtils.getHolesShapeGeometry(w, l, 0, r, scrp, count, 'z', true)

        vertices.push(...rightData[0]);
        indices.push(...rightData[1]);
        facevec.push([
            new Vector3(0, 0, 0),
            new Vector3(w, 0, 0),
            new Vector3(w, l, 0),
            new Vector3(0, l, 0)

        ]);

        count = rightData[2] + 1;

        // 角铝
        if (corner) {
            // 下挖孔
            let tpBottomVec = [
                new Vector3(0, -cort, 0),
                new Vector3(0, -cort, fh),
                new Vector3(w, -cort, fh),
                new Vector3(w, -cort, 0),
        
                new Vector3(0, -cort, 0)
            ]

            let tpTopVec = [
                new Vector3(0, 0, 0),
                new Vector3(0, 0, fh),
                new Vector3(w, 0, fh),
                new Vector3(w, 0, 0),

                new Vector3(0, 0, 0)
            ]

            let tpside = EntityUtils.getSideVIF(tpBottomVec, tpTopVec,   count);

            vertices.push(...tpside[0]);
            indices.push(...tpside[1]);
            facevec.push(...tpside[2]);
            count = tpside[3];

            let tbpos = EntityUtils.getPosByDis(tbp, dis);
            let leftData = EntityUtils.getHolesShapeGeometry(fh, w, -cort, r, tbpos, count, 'y', true)

            vertices.push(...leftData[0]);
            indices.push(...leftData[1]);
            facevec.push([
                new Vector3(0, -cort, 0),
                new Vector3(0, -cort, fh),
                new Vector3(w, -cort, fh),
                new Vector3(w, -cort, 0)
            ]);

            count = leftData[2] + 1;

            let rightData = EntityUtils.getHolesShapeGeometry(fh, w, 0, r, tbpos, count, 'y', false)

            vertices.push(...rightData[0]);
            indices.push(...rightData[1]);
            facevec.push([
                new Vector3(0, 0, 0),
                new Vector3(0, 0, fh),
                new Vector3(w, 0, fh),
                new Vector3(w, 0, 0)
            ]);

            count = rightData[2] + 1;
            // 

            let bvec = [
                new Vector3(0, -ch, 0),
                new Vector3(0, -ch, cort),
                new Vector3(w, -ch, cort),
                new Vector3(w, -ch, 0),
    
                new Vector3(0, -ch, 0)
            ]

            let tvec = [
                new Vector3(0, 0, 0),
                new Vector3(0, 0, cort),
                new Vector3(w, 0, cort),
                new Vector3(w, 0, 0),

                new Vector3(0, 0, 0)
            ]

            let cornerData = EntityUtils.getVIF(bvec, tvec, count);

            vertices.push(...cornerData[0]);
            indices.push(...cornerData[1]);
            facevec.push(...cornerData[2]);

            count = cornerData[3] + 4;
        }

        return [vertices, indices, facevec];
    }

    static getSideVIF(bottomVec: Vector3[], topVec: Vector3[], vertexCount: number): any[] {
        let face: Vector3[];

        let faceVec: any[] = [];
        let vertex: any[] = [];
        let index: any[] = [];

        // 侧面
        for (let i = 0; i < bottomVec.length - 1; i++) {
            // 顶点
            vertex.push(topVec[i].x, topVec[i].y, topVec[i].z);
            vertex.push(topVec[i + 1].x, topVec[i + 1].y, topVec[i + 1].z);

            vertex.push(bottomVec[i].x, bottomVec[i].y, bottomVec[i].z);
            vertex.push(bottomVec[i + 1].x, bottomVec[i + 1].y, bottomVec[i + 1].z);
            // 索引
            index.push(vertexCount + i, vertexCount + i + 2, vertexCount + i + 1);
            index.push(vertexCount + i + 2, vertexCount + i + 3, vertexCount + i + 1);
            // 面
            face = [];
            face.push(topVec[i], topVec[i + 1], bottomVec[i + 1], bottomVec[i]);
            faceVec.push(face);

            vertexCount += 3;
        };
        vertexCount += 4;
        return [vertex, index, faceVec, vertexCount];
    }


    static getVIF(bottomVec: Vector3[], topVec: Vector3[], vertexCount: number = 0): any[] {

        let face: Vector3[];

        let faceVec: any[] = [];
        let vertex: any[] = [];
        let index: any[] = [];

        // 侧面
        for (let i = 0; i < bottomVec.length - 1; i++) {
            // 顶点
            vertex.push(topVec[i].x, topVec[i].y, topVec[i].z);
            vertex.push(topVec[i + 1].x, topVec[i + 1].y, topVec[i + 1].z);

            vertex.push(bottomVec[i].x, bottomVec[i].y, bottomVec[i].z);
            vertex.push(bottomVec[i + 1].x, bottomVec[i + 1].y, bottomVec[i + 1].z);
            // 索引
            index.push(vertexCount + i, vertexCount + i + 2, vertexCount + i + 1);
            index.push(vertexCount + i + 2, vertexCount + i + 3, vertexCount + i + 1);
            // 面
            face = [];
            face.push(topVec[i], topVec[i + 1], bottomVec[i + 1], bottomVec[i]);
            faceVec.push(face);

            vertexCount += 3;
        }
        // 底面
        vertexCount += 4;

        vertex.push(bottomVec[0].x, bottomVec[0].y, bottomVec[0].z);
        vertex.push(bottomVec[1].x, bottomVec[1].y, bottomVec[1].z);
        vertex.push(bottomVec[3].x, bottomVec[3].y, bottomVec[3].z);
        vertex.push(bottomVec[2].x, bottomVec[2].y, bottomVec[2].z);

        index.push(vertexCount, vertexCount + 2, vertexCount + 1);
        index.push(vertexCount + 2, vertexCount + 3, vertexCount + 1);

        face = [];
        face.push(bottomVec[0], bottomVec[1], bottomVec[2], bottomVec[3]);
        faceVec.push(face);

        vertexCount += 4;
        vertex.push(topVec[0].x, topVec[0].y, topVec[0].z);
        vertex.push(topVec[1].x, topVec[1].y, topVec[1].z);
        vertex.push(topVec[3].x, topVec[3].y, topVec[3].z);
        vertex.push(topVec[2].x, topVec[2].y, topVec[2].z);

        index.push(vertexCount, vertexCount + 1, vertexCount + 2);
        index.push(vertexCount + 2, vertexCount + 1, vertexCount + 3);

        face = [];
        face.push(topVec[0], topVec[1], topVec[2], topVec[3]);
        faceVec.push(face);

        vertexCount += 4;

        return [vertex, index, faceVec, vertexCount];

    }

    /**
     * 获取带洞的板
     * @param w 
     * @param h 
     * @param dis 
     * @param r 
     * @param pos 
     * @returns 
     */
    static getHolesShapeGeometry(w: number, h: number, x: number, r: number, pos: any[], count: number, type: string = 'x', reverse: boolean = false): any[] {

        let leftShape = new Shape()
            .moveTo(0, 0)
            .lineTo(w, 0)
            .lineTo(w, h)
            .lineTo(0, h)
            .lineTo(0, 0);

        let pathVec: any[] = [];
        for (let i = 0; i < pos.length; i++) {
            let leftHolePath = new Path()
                .moveTo(pos[i][0], pos[i][1])
                .absarc(pos[i][0], pos[i][1], r / 2, 0, Math.PI * 2, true);
            pathVec.push(leftHolePath);
        }
        leftShape.holes.push(...pathVec);

        let geometry = new ShapeGeometry(leftShape);

        let bposition = geometry.attributes.position;
        let bindex = geometry.getIndex();

        // 顶点
        let vertices: any[] = [];
        for (let i = 0; i < bposition.array.length; i += 3) {
            let a = bposition.array[i];
            let b = bposition.array[i + 1];
            let c = bposition.array[i + 2];
            type === 'x' ? vertices.push(x, b, a) :
                type === 'y' ? vertices.push(b, x, a) :
                    type === 'z' ? vertices.push(a, b, x) : null;
        }

        // 索引
        let mx: number = 0;
        let indices: any[] = [];
        for (let i = 0; i < bindex.array.length; i += 3) {
            let a = bindex.array[i] + count;
            let b = bindex.array[i + 1] + count;
            let c = bindex.array[i + 2] + count;

            indices.push(a, b, c);
        }
        reverse ? indices.reverse() : null;
        mx = Math.max(...indices);

        return [vertices, indices, mx];
    }


    static getPosByDis(vec: any[], val: number): any[] {
        let pos: any[] = [];
        for (let i = 0; i < vec.length; i++) {
            pos.push([val, vec[i]])
        }
        return pos;
    }



}